package com.sale.goods.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sale.common.core.constant.CacheNames;
import com.sale.common.core.exception.GlobalException;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.mybatis.core.page.PageQuery;
import com.sale.common.mybatis.core.page.TableDataInfo;
import com.sale.common.redis.utils.CacheUtils;
import com.sale.common.satoken.utils.LoginHelper;
import com.sale.goods.domain.*;
import com.sale.goods.domain.dto.GoodsNuclearDto;
import com.sale.goods.domain.dto.single.GoodsNuclearSingle;
import com.sale.goods.domain.vo.GoodsNuclearVo;
import com.sale.goods.mapper.*;
import com.sale.goods.service.IGoodsNuclearService;
import com.sale.order.api.RemoteCustomerService;
import com.sale.order.api.RemoteSupplierService;
import com.sale.order.api.dto.CustomerBalance;
import com.sale.storage.api.RemotePurchaseReceiptService;
import com.sale.storage.api.vo.QuantityDataVo;
import com.sale.storage.api.vo.UpdateInvoicedQuantityVo;
import com.sale.system.api.RemoteCodeService;
import com.sale.system.api.RemoteReviewService;
import com.sale.system.api.domain.SysDictData;
import com.sale.system.api.domain.vo.SysAuditHistoryVo;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 核销单实现类
 * @Date 23-08-14
 * @Author hl
 **/
@RequiredArgsConstructor
@Service
public class GoodsNuclearServiceImpl implements IGoodsNuclearService {

    private final GoodsNuclearMapper goodsNuclearMapper;

    private final GoodsNuclearPreMapper goodsNuclearPreMapper;

    private final GoodsNuclearShouldMapper goodsNuclearShouldMapper;

    private final GoodsCollectionMapper goodsCollectionMapper;

    private final GoodsPaymentMapper goodsPaymentMapper;

    private final GoodsIncomeMapper goodsIncomeMapper;

    private final GoodsDisburseMapper goodsDisburseMapper;

    @DubboReference
    private final RemoteReviewService remoteReviewService;

    @DubboReference
    private final RemoteCodeService remoteCodeService;

    @DubboReference
    private final RemotePurchaseReceiptService remotePurchaseReceiptService;

    @DubboReference
    private final RemoteCustomerService remoteCustomerService;

    @DubboReference
    private final RemoteSupplierService remoteSupplierService;


    /**
     * 分页查询核销单
     *
     * @param goodsNuclearVo,pageQuery
     * @return TableDataInfo<GoodsNuclearDto>
     */
    @Override
    public TableDataInfo<GoodsNuclearDto> selectNuclearList(GoodsNuclearVo goodsNuclearVo, PageQuery pageQuery) {
        Page<GoodsNuclearDto> page = goodsNuclearMapper.selectNuclearList(pageQuery.build(), this.buildQueryWrapper(goodsNuclearVo));
        List<SysDictData> netArray = CacheUtils.get(CacheNames.SYS_DICT, "bill_state");
        List<SysDictData> netArray2 = CacheUtils.get(CacheNames.SYS_DICT, "goods_cancel_status");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        Map<String, String> netMap2 = netArray2.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //客户
        Map<String, String> map5 = remoteCustomerService.getOpenCustomerFinance();
        //供应商
        Map<String, String> map6 = remoteSupplierService.getOpenSupplierFinance();
        List<GoodsNuclearDto> list = page.getRecords();
        for (GoodsNuclearDto dto :
            list) {
            String nuclearType = dto.getNuclearType();
            if(nuclearType.equals("4")){
                dto.setClientCode(dto.getClientCodeInto());
            }
            if(nuclearType.equals("5")){
                dto.setSupplierCode(dto.getSupplierCodeInto());
            }
            String code = dto.getClientCode();
            if (StringUtils.isNotEmpty(code)) {
                dto.setClientName(map5.get(dto.getClientCode()));
            }
            String name1 = dto.getSupplierCode();
            if (StringUtils.isNotEmpty(name1)) {
                dto.setSupplierName(map6.get(dto.getSupplierCode()));
            }
            dto.setNuclearStatusDict(netMap.get(String.valueOf(dto.getNuclearStatus())));
            dto.setNuclearTypeDict(netMap2.get(String.valueOf(dto.getNuclearType())));
        }
        return TableDataInfo.build(page);
    }

    private Wrapper<GoodsNuclearVo> buildQueryWrapper(GoodsNuclearVo goodsNuclearVo) {
        Map<String, Object> params = goodsNuclearVo.getParams();
        QueryWrapper<GoodsNuclearVo> wrapper = Wrappers.query();
        wrapper
            .eq(StringUtils.isNotBlank(goodsNuclearVo.getNuclearCode()), "nuclear_code", goodsNuclearVo.getNuclearCode())
            .eq(StringUtils.isNotBlank(goodsNuclearVo.getNuclearStatus()), "nuclear_status", goodsNuclearVo.getNuclearStatus())
            .eq(StringUtils.isNotBlank(goodsNuclearVo.getNuclearType()), "nuclear_type", goodsNuclearVo.getNuclearType()).between(params.get("beginTime") != null && params.get("endTime") != null,
                "t1.invoice_time", params.get("beginTime"), params.get("endTime"));
        return wrapper;
    }

    /**
     * 新增核销单
     *
     * @param goodsNuclearVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertNuclear(GoodsNuclearVo goodsNuclearVo) throws Exception {
        //int type = Integer.parseInt(goodsNuclearVo.getNuclearType());
        Long nuclearId = IdWorker.getId();
        //新增明细1
        List<GoodsNuclearPre> list1 = goodsNuclearVo.getList1();
        BigDecimal b1 = new BigDecimal(0);
        for (GoodsNuclearPre pre :
            list1) {
            pre.setNuclearId(nuclearId);
            b1 = b1.add(pre.getPreNuclearAmount());
        }
        goodsNuclearPreMapper.insertBatch(list1);
        //新增明细2
        List<GoodsNuclearShould> list2 = goodsNuclearVo.getList2();
        if (list2 != null) {
            list2.stream().forEach(goodsNuclearShould -> goodsNuclearShould.setNuclearId(nuclearId));
            goodsNuclearShouldMapper.insertBatch(list2);
        }
        GoodsNuclear nuclear = new GoodsNuclear();
        BeanUtils.copyProperties(goodsNuclearVo, nuclear);
        nuclear.setNuclearStatus("1");
        nuclear.setNuclearId(nuclearId);
        nuclear.setNuclearAmount(b1);
        String authorityCoding = remoteCodeService.authorityCoding("finance:writeOff:list");
        if (authorityCoding == null) {
            throw new GlobalException("未进行单据配置,单据编码生成失败");
        }
        nuclear.setNuclearCode(authorityCoding);
        return goodsNuclearMapper.insert(nuclear);
    }

    /**
     * 查询单个核销单
     *
     * @param nuclearId
     * @return int
     */
    @Override
    public GoodsNuclearSingle selectNuclearById(long nuclearId) {
        GoodsNuclear nuclear = goodsNuclearMapper.selectById(nuclearId);
        GoodsNuclearSingle single = new GoodsNuclearSingle();
        BeanUtils.copyProperties(nuclear, single);
        String type = nuclear.getNuclearType();
        Map<String, Object> map = new HashMap<>();
        map.put("nuclear_id", nuclearId);
        single.setList1(goodsNuclearPreMapper.selectByMap(map));
        if (!type.equals("5") && !type.equals("4")) {
            //代表有明细且查询
            single.setList2(goodsNuclearShouldMapper.selectByMap(map));
        }
        return single;
    }

    /**
     * 修改单个核销单
     *
     * @param goodsNuclearVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateNuclearEdit(GoodsNuclearVo goodsNuclearVo) {
        if (goodsNuclearVo.getNuclearStatus().equals("4")) {
            SysAuditHistoryVo vo = new SysAuditHistoryVo();
            vo.setPerms("finance:writeOff:examine");
            vo.setAuditDoc(goodsNuclearVo.getNuclearCode());
            int is = remoteReviewService.editHistory(vo);
            if (is == 0) {
                throw new GlobalException("修改失败,未找到审核历史!");
            }
        }
        Long nuclearId = goodsNuclearVo.getNuclearId();
        Map<String, Object> map = new HashMap<>();
        map.put("nuclear_id", nuclearId);
        goodsNuclearPreMapper.deleteByMap(map);
        goodsNuclearShouldMapper.deleteByMap(map);
        List<GoodsNuclearPre> list1 = goodsNuclearVo.getList1();
        BigDecimal b1 = new BigDecimal(0);
        for (GoodsNuclearPre pre :
            list1) {
            pre.setNuclearId(nuclearId);
            b1 = b1.add(pre.getPreNuclearAmount());
        }
        goodsNuclearPreMapper.insertBatch(list1);
        List<GoodsNuclearShould> list2 = goodsNuclearVo.getList2();
        if (list2 != null) {
            list2.stream().forEach(goodsNuclearShould -> goodsNuclearShould.setNuclearId(nuclearId));
            goodsNuclearShouldMapper.insertBatch(list2);
        }
        GoodsNuclear goodsNuclear = new GoodsNuclear();
        BeanUtils.copyProperties(goodsNuclearVo, goodsNuclear);
        goodsNuclear.setNuclearAmount(b1);
        goodsNuclear.setNuclearStatus("1");
        int os = goodsNuclearMapper.updateById(goodsNuclear);
        if (os == 0) {
            throw new GlobalException("未查到该数据");
        }
        return os;
    }

    /**
     * 删除单个核销单
     *
     * @param nuclearId
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteNuclearById(Long nuclearId) {
        Map<String, Object> map = new HashMap<>();
        map.put("nuclear_id", nuclearId);
        goodsNuclearPreMapper.deleteByMap(map);
        goodsNuclearShouldMapper.deleteByMap(map);
        return goodsNuclearMapper.deleteById(nuclearId);
    }

    /**
     * 提交审核
     *
     * @param nuclearId
     * @return int
     */
    @Override
    public int submitReview(Long nuclearId) {
        GoodsNuclear goodsNuclear = goodsNuclearMapper.selectById(nuclearId);
        String status = goodsNuclear.getNuclearStatus();
        if (!status.equals("1")) {
            throw new GlobalException("只有待提交状态才能进行提交审核");
        }
        GoodsNuclear nuclear = new GoodsNuclear();
        nuclear.setNuclearStatus("2");
        nuclear.setNuclearId(nuclearId);
        return goodsNuclearMapper.updateById(nuclear);
    }

    /**
     * 撤销审核
     *
     * @param nuclearId
     * @return int
     */
    @Override
    public int deleteReview(Long nuclearId) {
        GoodsNuclear goodsNuclear = goodsNuclearMapper.selectById(nuclearId);
        String status = goodsNuclear.getNuclearStatus();
        if (!status.equals("2")) {
            throw new GlobalException("只有待审核状态才能进行撤销审核");
        }
        GoodsNuclear nuclear = new GoodsNuclear();
        nuclear.setNuclearStatus("1");
        nuclear.setNuclearId(nuclearId);
        return goodsNuclearMapper.updateById(nuclear);
    }

    /**
     * 审核单据
     *
     * @param goodsNuclearVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int goodSExamineReview(GoodsNuclearVo goodsNuclearVo) throws Exception {
        SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
        Long id = goodsNuclearVo.getNuclearId();
        GoodsNuclear goodsNuclear = goodsNuclearMapper.selectById(id);
        String perms = "finance:writeOff:examine";
        sysAuditHistoryVo.setPerms(perms);
        sysAuditHistoryVo.setModuleType(3);
        sysAuditHistoryVo.setAuditState(goodsNuclearVo.getAuditState());
        sysAuditHistoryVo.setAuditRemarks(goodsNuclearVo.getAuditOpinion());
        sysAuditHistoryVo.setAuditDoc(goodsNuclear.getNuclearCode());
        sysAuditHistoryVo.setUserId(LoginHelper.getUserId());
        int data = remoteReviewService.getSequence(sysAuditHistoryVo);
        if (data == 0) {
            throw new GlobalException("未对该审核进行配置");
        }
        //1:通过，2：审核中，3：没权限 4:该人已经审核过
        GoodsNuclear goods = new GoodsNuclear();
        goods.setNuclearId(id);
        switch (data) {
            case 1:
                if (goodsNuclearVo.getAuditState() == 2) {
                    goods.setNuclearStatus("4");
                } else {
                    goods.setNuclearStatus("5");
                    String type = goodsNuclear.getNuclearType();
                    Map<String, Object> map1 = new HashMap<>();
                    map1.put("nuclear_id", id);
                    List<QuantityDataVo> dataList = new ArrayList<>();
                    UpdateInvoicedQuantityVo quantityVo = new UpdateInvoicedQuantityVo();
                    BigDecimal balance = BigDecimal.ZERO;

                    if (type.equals("1")) {
                        List<GoodsNuclearPre> list2 = goodsNuclearPreMapper.selectByMap(map1);
                        for (GoodsNuclearPre pre : list2) {
                            GoodsCancel cancel = new GoodsCancel();
                            cancel.setReceiptNumber(pre.getPreCode());
                            cancel.setApprovedAmount(pre.getPreNuclearAmount());
                            if (pre.getNotAfterAmount().subtract(pre.getPreNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                cancel.setStatus(1);
                            } else {
                                cancel.setStatus(3);
                            }
                            goodsCollectionMapper.renewalAndCancellation(cancel);
                        }

                        List<GoodsNuclearShould> list3 = goodsNuclearShouldMapper.selectByMap(map1);
                        for (GoodsNuclearShould should : list3) {
                            if (should.getShouldType().equals("其他收入")) {
                                GoodsCancel cancel = new GoodsCancel();
                                cancel.setReceiptNumber(should.getShouldCode());
                                cancel.setApprovedAmount(should.getShouldNuclearAmount());
                                if (should.getNotAfterAmount().subtract(should.getShouldNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                    cancel.setStatus(1);
                                } else {
                                    cancel.setStatus(3);
                                }
                                goodsIncomeMapper.updateInvoicedCancel(cancel);
                            } else {
                                QuantityDataVo vo = new QuantityDataVo();
                                vo.setReceiptNumber(should.getShouldCode());
                                vo.setQuantity("1");
                                vo.setApprovedAmount(should.getShouldNuclearAmount());
                                vo.setDocumentType(should.getShouldType());
                                dataList.add(vo);
                            }
                        }
                    } else if (type.equals("2")) {
                        List<GoodsNuclearPre> list2 = goodsNuclearPreMapper.selectByMap(map1);
                        for (GoodsNuclearPre pre : list2) {
                            GoodsCancel cancel = new GoodsCancel();
                            cancel.setReceiptNumber(pre.getPreCode());
                            cancel.setApprovedAmount(pre.getPreNuclearAmount());
                            if (pre.getNotAfterAmount().subtract(pre.getPreNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                cancel.setStatus(1);
                            } else {
                                cancel.setStatus(3);
                            }
                            goodsPaymentMapper.paymentAndCancellation(cancel);
                        }

                        List<GoodsNuclearShould> list3 = goodsNuclearShouldMapper.selectByMap(map1);
                        for (GoodsNuclearShould should : list3) {
                            if (should.getShouldType().equals("其他支出")) {
                                GoodsCancel cancel = new GoodsCancel();
                                cancel.setReceiptNumber(should.getShouldCode());
                                cancel.setApprovedAmount(should.getShouldNuclearAmount());
                                if (should.getNotAfterAmount().subtract(should.getShouldNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                    cancel.setStatus(1);
                                } else {
                                    cancel.setStatus(3);
                                }
                                goodsDisburseMapper.updateDisburseCancel(cancel);
                            } else {
                                QuantityDataVo vo = new QuantityDataVo();
                                vo.setReceiptNumber(should.getShouldCode());
                                vo.setQuantity("1");
                                vo.setApprovedAmount(should.getShouldNuclearAmount());
                                vo.setDocumentType(should.getShouldType());
                                dataList.add(vo);
                            }
                        }
                    } else if (type.equals("3")) {
                        List<GoodsNuclearPre> list3 = goodsNuclearPreMapper.selectByMap(map1);
                        for (GoodsNuclearPre pre : list3) {
                            QuantityDataVo vo = new QuantityDataVo();
                            vo.setReceiptNumber(pre.getPreCode());
                            vo.setQuantity("1");
                            balance = balance.add(pre.getPreNuclearAmount());
                            vo.setApprovedAmount(pre.getPreNuclearAmount());
                            vo.setDocumentType(pre.getPreType());
                            dataList.add(vo);
                        }

                        List<GoodsNuclearShould> list4 = goodsNuclearShouldMapper.selectByMap(map1);
                        for (GoodsNuclearShould should : list4) {
                            QuantityDataVo vo = new QuantityDataVo();
                            vo.setReceiptNumber(should.getShouldCode());
                            vo.setQuantity("1");
                            balance = balance.add(should.getShouldNuclearAmount());
                            vo.setApprovedAmount(should.getShouldNuclearAmount());
                            vo.setDocumentType(should.getShouldType());
                            dataList.add(vo);
                        }
                    } else if (type.equals("4")) {
                        List<GoodsNuclearPre> list3 = goodsNuclearPreMapper.selectByMap(map1);
                        for (GoodsNuclearPre pre : list3) {
                            if (pre.getPreType().equals("其他收入")) {
                                GoodsCancel cancel = new GoodsCancel();
                                cancel.setReceiptNumber(pre.getPreCode());
                                cancel.setApprovedAmount(pre.getPreNuclearAmount());
                                balance = balance.add(pre.getPreNuclearAmount());
                                if (pre.getNotAfterAmount().subtract(pre.getPreNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                    cancel.setStatus(1);
                                } else {
                                    cancel.setStatus(3);
                                }
                                goodsIncomeMapper.updateInvoicedCancel(cancel);
                            } else {
                                QuantityDataVo vo = new QuantityDataVo();
                                vo.setReceiptNumber(pre.getPreCode());
                                vo.setQuantity("1");
                                balance = balance.add(pre.getPreNuclearAmount());
                                vo.setApprovedAmount(pre.getPreNuclearAmount());
                                vo.setDocumentType(pre.getPreType());
                                dataList.add(vo);
                            }
                        }
                    } else {
                        List<GoodsNuclearPre> list3 = goodsNuclearPreMapper.selectByMap(map1);
                        for (GoodsNuclearPre pre : list3) {
                            if (pre.getPreType().equals("其他支出")) {
                                GoodsCancel cancel = new GoodsCancel();
                                cancel.setReceiptNumber(pre.getPreCode());
                                cancel.setApprovedAmount(pre.getPreNuclearAmount());
                                balance = balance.add(pre.getPreNuclearAmount());
                                if (pre.getNotAfterAmount().subtract(pre.getPreNuclearAmount()).compareTo(BigDecimal.ZERO) > 0) {
                                    cancel.setStatus(1);
                                } else {
                                    cancel.setStatus(3);
                                }
                                goodsDisburseMapper.updateDisburseCancel(cancel);
                            } else {
                                QuantityDataVo vo = new QuantityDataVo();
                                vo.setReceiptNumber(pre.getPreCode());
                                vo.setQuantity("1");
                                balance = balance.add(pre.getPreNuclearAmount());
                                vo.setApprovedAmount(pre.getPreNuclearAmount());
                                vo.setDocumentType(pre.getPreType());
                                dataList.add(vo);
                            }
                        }
                    }
                    if(dataList.size()>0){
                        quantityVo.setList(dataList);
                        boolean flag = remotePurchaseReceiptService.updateInvoicedQuantity(quantityVo);
                        if (!flag) {
                            throw new GlobalException("核销数据未更新，请重试");
                        }
                    }
                    if (type.equals("4")) {
                        CustomerBalance customer = new CustomerBalance();
                        customer.setCustomerNum(goodsNuclear.getClientCodeInto());
                        customer.setBalance(balance);
                        remoteCustomerService.updateClientBalance(customer);
                    } else {
                        CustomerBalance customer = new CustomerBalance();
                        customer.setCustomerNum(goodsNuclear.getSupplierCodeInto());
                        customer.setBalance(balance);
                        remoteSupplierService.updateSupplierBalance(customer);
                    }
                }
                break;
            case 2:
                goods.setNuclearStatus("3");
                break;
            case 3:
                if (data == 0) {
                    throw new GlobalException("不具备审核权限");
                }
                break;
            case 4:
                if (data == 4) {
                    throw new GlobalException("请勿重复审核");
                }
                break;
        }
        //审核人
        goods.setExamineBy(LoginHelper.getUsername());
        //审核日期
        goods.setExamineTime(new Date());
        return goodsNuclearMapper.updateById(goods);
    }
}
